package com.example.emos.wx.service.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateRange;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.unit.DataUnit;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.example.emos.wx.config.SystemConstants;
import com.example.emos.wx.db.dao.*;
import com.example.emos.wx.db.pojo.TbCheckin;
import com.example.emos.wx.db.pojo.TbUser;
import com.example.emos.wx.db.pojo.TbWorkday;
import com.example.emos.wx.exception.EmosException;
import com.example.emos.wx.service.CheckinService;
import com.example.emos.wx.task.EmailTask;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Jsoup;
import org.jsoup.helper.DataUtil;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Set;

@Slf4j
@Scope("prototype")
@Service
public class CheckinServiceImpl implements CheckinService {

    @Autowired
    private SystemConstants constants;

    @Autowired
    private TbHolidaysDao holidaysDao;

    @Autowired
    private TbWorkdayDao workdayDao;

    @Autowired
    private TbCheckinDao checkinDao;

    @Autowired
    private TbFaceModelDao faceModelDao;

    @Autowired
    private TbUserDao userDao;

    @Autowired
    private TbCityDao cityDao;

    @Value("${emos.email.hr}")
    private String hrEmail;

    @Autowired
    private EmailTask emailTask;

    @Override
    public String validCanCheckIn(int userId, String date) {
        //先判断是否是特殊的节假日
        boolean bool_1 = holidaysDao.searchTodayIsHolidays() != null ? true : false;
        boolean bool_2 = workdayDao.searchTodayIsWorkday() != null ? true : false;

        String type = "工作日";
        if (DateUtil.date().isWeekend()){
            type = "节假日";
        }
        if (bool_1){
            type = "节假日";
        }else if (bool_2){
            type = "工作日";
        }

        if (type.equals("节假日")){
            return "节假日不需要考勤";
        }else {
            DateTime now = DateUtil.date();
            String start = DateUtil.today()+" "+constants.attendanceStartTime;
            String end = DateUtil.today()+" "+constants.attendanceEndTime;
            DateTime attendanceStart = DateUtil.parse(start);
            DateTime attendanceEnd = DateUtil.parse(end);

            //看看现在的时间是不是在考勤时间之前
            if (now.isBefore(attendanceStart)){
                return "还没到上班考勤的时间";
            }else if (now.isAfter(attendanceEnd)){
                return "超过了上班考勤结束时间";
            }else {
                //可以进行考勤
                HashMap map = new HashMap();
                map.put("userId", userId);
                map.put("date", date);
                map.put("start", start);
                map.put("end", end);
                boolean bool = checkinDao.haveCheckin(map) != null ? true : false;
                return bool ? "今日已经考勤，不用重复考勤" : "可以考勤";
            }
        }
    }

    @Override
    public void checkin(HashMap param) {
        Date d1=DateUtil.date();
        //将日期字符串转换为日期对象(上班时间)
        Date d2=DateUtil.parse(DateUtil.today()+" "+constants.attendanceTime);
        //上班结束时间
        Date d3=DateUtil.parse(DateUtil.today()+" "+constants.attendanceEndTime);

        //status为1的时候代表的是正常考勤
        int status = 1;
        if (d1.compareTo(d2) <= 0){
            status = 1;
        }else if (d1.compareTo(d2) > 0 && d1.compareTo(d3) < 0){
            //为2表示迟到
            status = 2;
        }
        int userId = (Integer) param.get("userId");
//        String faceModel = faceModelDao.searchFaceModel(userId);
        /*
            由于没有人脸识别的程序，这里的人脸模型就默认是本人签到了
         */
//        if (faceModel == null){
//            throw new EmosException("不存在人脸模型");
//        }
//        else {
//            String path = (String) param.get("path");


//            TbUser user = userDao.searchById(userId);
//            String openId = user.getOpenId();

            //发送http请求
           /* HttpRequest request = HttpUtil.createPost(url);
            //这样就能上传文件了
            request.form("photo", FileUtil.file(path),"targetModel",faceModel);
            HttpResponse response = request.execute();
            if(reponse.getStatus() != 200){
                log.error("人脸识别服务异常");
            }
            //获得返回回来的响应体
            String body = response.body;
            if("无法识别处人脸".equals(body) || "照片中存在多张人脸".equals(body)){
                throw new EmosException(body);
            }
            //如果不是同一个人
            else if("False".equals(body)){
                throw new EmosException("签到失败，非本人签到");
            }
            else if("True".equals(body)){
                //人脸数据一致，判断疫情风险等级
            }*/


            //查询疫情风险等级
            //默认1 为低风险 3 为高风险
            int risk = 1;
            //查询城市代码
            String city = (String) param.get("city");
            String district = (String) param.get("district");
            String address = (String) param.get("address");
            String country = (String) param.get("country");
            String province = (String) param.get("province");
            if (!StrUtil.isBlank(city) && !StrUtil.isBlank(district)){
                //如果城市和区县都不为空的话
                String code = cityDao.searchCode(city);
                try {
                    String url = "http://m." + code + ".bendibao.com/news/yqdengji/?qu=" + district;
                    //加载页面并保存为document对象
                    Document document = Jsoup.connect(url).get();
                    //通过类选择器找到那个div标签，并封装到一个集合中
                    Elements elements = document.getElementsByClass("list-content");

                    if (elements.size() > 0){
                        //取出第一个元素
                        Element element = elements.get(0);
                        //获取到第二个p标签里面的内容
                        String result = element.select("p:last-child").text();

                        result = "高风险";
                        if ("高风险".equals(result)){
                            risk = 3;
                            //发送警告邮件
                            HashMap<String, String> map = userDao.searchNameAndDept(userId);
                            String name = map.get("name");
                            String deptName = map.get("dept_name");
                            deptName = deptName != null ? deptName : "";
                            //创建邮件封装对象
                            SimpleMailMessage message = new SimpleMailMessage();
                            //设置收件人
                            message.setTo(hrEmail);
                            //设置邮件标题
                            message.setSubject("员工" + name + "身处高风险疫情地区警告");
                            message.setText(deptName + "员工" + name + ", " + DateUtil.format(new Date(), "yyyy年MM月dd日") + "处于" + address + "，属于高风险地区，警告！");
                            emailTask.seadAsync(message);
                        }else if ("中风险".equals(result)){
                            risk = 2;
                        }
                    }
                }catch (Exception e){
                    log.error("执行异常",e);
                    throw new EmosException("获取风险等级失败");
                }


            }

            //保存签到记录
            TbCheckin entity = new TbCheckin();
            entity.setUserId(userId);
            entity.setCountry(country);
            entity.setAddress(address);
            entity.setProvince(province);
            entity.setCity(city);
            entity.setDistrict(district);
            entity.setRisk(risk);
            //正常签到还是迟到
            entity.setStatus((byte) status);
            entity.setDate(DateUtil.today());
            entity.setCreateTime(d1);
            checkinDao.insert(entity);
//        }
    }

    @Override
    public HashMap searchTodayCheckin(int userId) {
        HashMap map = checkinDao.searchTodayCheckin(userId);
        return map;
    }

    @Override
    public long searchCheckinDays(int userId) {
        long days = checkinDao.searchCheckinDays(userId);
        return days;
    }

    @Override
    public ArrayList<HashMap> searchWeekCheckin(HashMap param) {
        //查询本周内的考勤情况
        ArrayList<HashMap> checkinList = checkinDao.searchWeekCheckin(param);
        ArrayList<String> holidayList = holidaysDao.searchHolidaysInRange(param);
        ArrayList workdayList = workdayDao.searchWorkdayInRange(param);

        DateTime startDate = DateUtil.parseDate(param.get("startDate").toString());
        DateTime endDate = DateUtil.parseDate(param.get("endDate").toString());
        //生成一周内的日期对象
        DateRange range = DateUtil.range(startDate, endDate, DateField.DAY_OF_MONTH);
        ArrayList<HashMap> list = new ArrayList<>();

        range.forEach(one->{
            String date = one.toString("yyyy-MM-dd");
            String type = "工作日";
            if (one.isWeekend()){
                type = "节假日";
            }
            if (holidayList != null && holidayList.contains(date)){
                type = "节假日";
            }else if (workdayList != null && workdayList.contains(date)){
                type = "工作日";
            }
            String status = "";
            boolean flag = false;
            //判断one这一天是否是工作日 并且已经发生过了
            if (type.equals("工作日") && DateUtil.compare(one, DateUtil.date()) <= 0){
                status = "缺勤";
                //判断这一天的考勤情况
                for (HashMap<String, String> map : checkinList){
                    if (map.containsValue(date)){
                        status = map.get("status");
                        flag = true;
                        break;
                    }
                }
                DateTime endTime = DateUtil.parse(DateUtil.today() + " "+ constants.attendanceEndTime);
                String today = DateUtil.today();
                //如果那一天刚好是今天的话，再判断是否是在考勤结束时间之前
                if (date.equals(today) && DateUtil.date().isBefore(endTime) && flag == false){
                    status = "";
                }
            }

            HashMap map = new HashMap();
            map.put("date", date);
            map.put("status", status);
            map.put("type", type);
            map.put("day", one.dayOfWeekEnum().toChinese("周"));
            list.add(map);
        });
        return list;
    }

    @Override
    public ArrayList<HashMap> searchMonthCheckin(HashMap param) {
        return this.searchWeekCheckin(param);
    }
}
